<?php

namespace app\common\model\virtual;

use app\common\loader\ModelMerchant;
use app\common\loader\ModelShop;
use app\common\loader\ModelVirtual;
use app\common\model\BaseModel;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Exception;

/**
 * 虚码使用记录表
 * Class VirtualUsedLog
 * @package app\common\model\virtual
 */
class VirtualUsedLogModel extends BaseModel
{
    //
    protected $name = 'virtual_used_log';

    protected $json = ['product'];
    //
    public string $fieldId = 'id';
    // 商户码
    public string $fieldMerId = 'mer_id';
    // 虚码活动ID
    public string $fieldVpId = 'vp_id';
    // 门店ID
    public string $fieldShopId = 'shop_id';
    // 导购ID
    public string $fieldSalesmanId = 'salesman_id';
    // 商品货号
    public string $fieldProductCode = 'product_code';
    // 红包金额
    public string $fieldRedPacket = 'red_packet';
    // 积分
    public string $fieldPoint = 'point';
    // 状态 1已审核 0待审核,2审核失败
    public string $fieldStatus = 'status';
    // 失败原因
    public string $fieldFailReason = 'fail_reason';
    // 小票url
    public string $fieldTicketUrl = 'ticket_url';
    // 操作人|审核人
    public string $fieldOpUser = 'op_user';
    // 创建时间
    public string $fieldCreateAt = 'create_at';
    // 更新时间
    public string $fieldUpdateAt = 'update_at';
    // 虚码活动名称
    public string $fieldVpTitle = 'vp_title';
    // 门店名称
    public string $fieldShopTitle = 'shop_title';
    // 商品信息 [(code=>xx,product=xx,num=xx)]
    public string $fieldProduct = 'product';

    // 设置字段信息
    protected $schema = [
        'id' => 'int',        //
        'mer_id' => 'string',        // 商户码
        'vp_id' => 'int',        // 虚码活动ID
        'shop_id' => 'int',        // 门店ID
        'salesman_id' => 'int',        // 导购ID
        'product_code' => 'string',        // 商品货号
        'red_packet' => 'float',        // 红包金额
        'point' => 'int',        // 积分
        'status' => 'int',        // 状态 1已审核 0待审核,2审核失败
        'fail_reason' => 'string',        // 失败原因
        'ticket_url' => 'string',        // 小票url
        'op_user' => 'int',        // 操作人|审核人
        'create_at' => 'datetime',        // 创建时间
        'update_at' => 'datetime',        // 更新时间
    ];


    /**
     * 销售记录查询分页
     * @param array $virtual_where
     * @param int $page
     * @param int $page_size
     * @return mixed
     * @throws DbException
     */
    public function getMarket($virtual_where = [], $page = 1, $page_size = 30)
    {

        return $this->db('virtual_used_log')->where($virtual_where)
            ->field('id,red_packet,point,status,status as status_title,ticket_url,create_at,shop_title,
            vp_title,product,product as product_title,fail_reason,salesman_id as salesman_name')
            ->withAttr([
                'status_title' => function ($value) {
                    $status = ['1' => '已审核', '2' => '审核失败', '0' => '待审核', '3' => '支付失败', '8' => '已完成'];
                    return $status[$value];
                },
                'ticket_url' => function ($value) {
                if (!empty($value)){
                    return explode(',', $value);
                }
                    return  [];
                },
                'product_title' => function ($value) {
                    $data = json_decode($value, true);
                    $pro_title = '';
                    foreach ($data as $v) {
                        $pro_title .= $v['product_title'] . '*' . $v['num'] . '  ';
                    }
                    return $pro_title;
                },
                'salesman_name' => function ($value) {
                    return $this->db('shop_salesman')->where(['id' => $value])->value('name');
                }

            ])
            ->order('create_at desc')
            ->cache(true, MINUTES_SECOND)
            ->paginate(['page' => $page, 'list_rows' => $page_size]);
    }

    /**
     * 添加虚码使用记录表
     * @param        $mer_id
     * @param        $vp_id
     * @param        $shop_id
     * @param        $salesman_id
     * @param        $red_packet
     * @param        $point
     * @param        $status
     * @param        $ticket
     * @param        $op_user |操作人
     * @param        $vp_title | 活动名称
     * @param        $shop_title | 门店名称
     * @param        $product | 商品列表
     * @param string $op_user
     * @return int|string
     */
    public function add($mer_id, $vp_id, $shop_id, $salesman_id, $red_packet,
                        $point, $status, $ticket, $op_user = '', $vp_title = '', $shop_title = '', $product = '')
    {
        return $this->db()->insert([
            'mer_id' => $mer_id,
            'vp_id' => $vp_id,
            'shop_id' => $shop_id,
            'salesman_id' => $salesman_id,
            'red_packet' => $red_packet,
            'point' => $point,
            'status' => $status,
            'ticket_url' => $ticket,
            'op_user' => $op_user,
            'vp_title' => $vp_title,
            'shop_title' => $shop_title,
            'product' => $product,
        ], true);
    }

    /**
     * 使用列表
     * @param array $option
     * @return mixed
     * @throws DbException
     */
    public function pageList($merId, array $option)
    {
        $db = $this->db()->alias('a')->where($option['where'])
            ->withoutField('op_user')
            ->order($option['order'] ?? 'id desc');
        if (!empty($option['where_raw'])) {
            $db = $db->whereRaw($option['where_raw']);
        }
        // 查询支付状态
        if (!empty($option['where_pay'])) {
            $db = $db->whereIn('id', function ($query) use ($merId, $option) {
                if ((int)$option['where_pay'] === 1) {
                    $query->name('pending_red_packet')->where('status=1')->field('used_log_id');
                } else {
                    $query->name('pending_red_packet')->where('status=0 or status =2')->field('used_log_id');
                }
            });
        }
        return $db->paginate($option['page_size']);
    }

    /**
     * 详情
     * @param array $where
     * @return mixed
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException|Exception
     */
    public function getInfo(array $where = [])
    {
        $data = $this->db()->where($where)->field('id,red_packet,point,status,status as status_title,ticket_url,create_at,product,product,shop_title,
            vp_title,product as product_title,salesman_id,shop_id,mer_id,admin_id as admin_info,vp_id,fail_reason,admin_id')->withAttr([
            'status_title' => function ($value) {
                $status = ['1' => '已审核', '2' => '审核失败', '0' => '待审核'];
                return $status[$value] ?? '';
            },
            'ticket_url' => function ($value) {
                return explode(',', $value);
            },
            'product_title' => function ($value) {
                $data = json_decode($value, true);
                $pro_title = '';
                foreach ($data as $key => $v) {
                    $pro_title .= $v['product_title'] . '*' . $v['num'] . ' ';
                }
                return $pro_title;
            },
            'admin_info' => function ($value) {
                return  $this->db('merchant')->alias('m')->join('merchant_stock i','m.mer_id=i.mer_id')
                    ->where('id' , $value)
                    ->field('m.open_id,i.balance')
                    ->find();
            }
        ])->find();

        if (empty($data)) {
            throw  new Exception('未找到订单信息', API_ERROR);
        }
        $data['salesman_name'] = $this->db('shop_salesman')->where('id', $data['salesman_id'])->value('name');
        return $data;
    }


    /**
     * 审核修改状态
     * @param  $where |主键
     * @param  $status | 状态
     * @param  $user_id | 操作人
     * @param  $memo | 备注
     * @throws Exception
     */
    public function submitAudit($where, $status, $user_id, $memo = ''): bool
    {
        try {

            $virtualData = ModelVirtual::VirtualUsedLog()->getInfo($where);
            if (empty($virtualData)) {
                throw new Exception('订单不存在', API_ERROR);
            }
            if ($virtualData['status'] !== 0) {
                throw new Exception('当前订单已审核', API_ERROR);
            }

            $this->startTrans();

            $now = date('Y-m-d H:i:s');
            $updateData = [
                'status' => $status,
                'op_user' => $user_id,
                'update_at' => $now,
                'fail_reason' => $memo,
            ];
            if ($status === 1) {
                $this->sendPointAndRedPacket(
                    $virtualData['mer_id'],
                    $virtualData['salesman_id'],
                    $virtualData['point'],
                    $virtualData['red_packet'],
                    $virtualData['id']
                );

                // 不需要支付红包，默认为已完成
                if ((float)$virtualData['red_packet'] === 0.0) {
                    $updateData['status'] = 8;
                }
            }


            if ((int)$status === 2) {
                $this->db('pending_red_packet')->where('used_log_id', $virtualData['id'])
                    ->update(['status' => 2]);
                /*  $product = [];
                  foreach ($virtualData['product'] as $v) {
                      $product[$v['code']] = $v;
                  }
                  ModelShop::ShopStock()->updateShopStock($virtualData['shop_id'], (int)$virtualData['mer_id'], $product, false);
                  ModelVirtual::VirtualPromo()->updateStockMarket($virtualData['vp_id'], 1, 2);*/
            }

            $this->db()->where('id', $virtualData['id'])->update($updateData);
            $this->commit();
            return true;
        } catch (Exception $e) {
            $this->rollback();
            throw $e;
        }
    }


    /**
     *  给导购发放红包和积分
     * @param string $mer_id 商户ID
     * @param int $user_id 导购ID
     * @param int $point 积分数
     * @param float $red_packet 红包数
     * @param int $log_id 日志ID
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws Exception
     * @throws ModelNotFoundException
     */
    public function sendPointAndRedPacket(string $mer_id, int $user_id, int $point, float $red_packet, int $log_id): void
    {
        //更新导购积分
        if ($point > 0) {
            ModelShop::ShopSalesman()->salesmanSavePoint($user_id, $point, '销售商品积分');
        }

        //添加红包添加日志
        if ($red_packet > 0) {
            ModelMerchant::PendingRedPacket()->add($mer_id, 1, $log_id, $user_id, $red_packet);
        }
    }

    /**
     * 销售记录
     * @param array $virtual_where
     * @param int $limit
     * @return mixed
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getList(array $virtual_where = [], int $limit = 100)
    {

        return $this->db()->where($virtual_where)
            ->field('id,red_packet,point,status,status as status_title,ticket_url,create_at,product,shop_title,
            vp_title,product as product_title,salesman_id,salesman_id as salesman_name,fail_reason')
            ->withAttr([
                'status_title' => function ($value) {
                    $status = ['1' => '已审核', '2' => '审核失败', '0' => '待审核','3' => '支付失败','8' => '已完成'];
                    return $status[$value];
                },
                'ticket_url' => function ($value) {
                    return explode(',', $value);
                },
                'product_title' => function ($value) {
                    $data = json_decode($value, true);
                    $pro_title = '';
                    foreach ($data as $key => $v) {
                        $pro_title .= $v['product_title'] . '|';
                    }
                    return $pro_title;
                },
                'salesman_name' => function ($value) {
                    return $this->db('shop_salesman')->where('id',$value)
                        ->value('concat(name,\'|\',mobile,\'\')');
                }
            ])
            ->order('create_at desc')
            ->cache(true, MINUTES_SECOND)
            ->limit($limit)
            ->select();
    }

    /**
     * 商户统计信息
     * @param array $option
     * @return mixed
     * @throws DbException
     */
    public function promoUsedLogList(array $option = [])
    {
        return $this->db()
            ->group('mer_id')
            ->where($option ?? [])
            ->column('sum(case when status=8 then red_packet else 0 end) as red_packet,
            sum(case when status=8 then point else 0 end) as point,count(id) as order_sum','mer_id');
    }

    /**
     * 一周内商户统计信息
     * @param array $option
     * @return mixed
     * @throws DbException
     */
    public function promoUsedLogNum(array $option)
    {
        return $this->db()
            ->group('mer_id')
            ->where($option ?? [])
            ->column('count(case when status>0 then 1 else 0 end) as count','mer_id');
    }

    /**
     * 使用列表
     * @param array $option
     * @return mixed
     * @throws DbException
     */
    public function statisticpage($merId, array $option)
    {
        return $this->db()->where($option['where'])
            ->where('mer_id' , $merId)
            ->field('red_packet,salesman_id,create_at')
            ->order($option['order'] ?? 'id desc')->paginate($option['page_size']);
    }
}
